﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Windows.Input;
using DG.Common.EF.WPF;
using DG.Common.Patterns.Commands;
using DG.Common.Patterns.MVVM;
using TCC.ControleFluxoDeCaixa.Model.Contas;
using TCC.ControleFluxoDeCaixa.Model.Entities;
using TCC.ControleFluxoDeCaixa.Model.Fluxo;
using TCC.ControleFluxoDeCaixa.Model.Gerenciadores;
using TCC.ControleFluxoDeCaixa.Model.Usuarios;

namespace TCC.ControleFluxoDeCaixa.Apresentacao.ViewModels
{
    public class EmprestimoCadastroWindowViewModel : EntityCRUDViewModelBase<FluxoDeCaixaContextFiltrado, Emprestimo>
    {
        private Lancamento _lancamentoPagamento;
        private Lancamento _lancamentoSaida;
        private decimal _valor;
        private bool _pagamentoRealizado;
        private DateTime _dataDoPagamento = DateTime.Now;
        private ContaFinanceira _conta;

        public IEnumerable<Pessoa> GetPessoas
        {
            get
            {
                return Context == null ? null : Context.Pessoas.ToArray();
            }
        }
        public IEnumerable<ContaFinanceira> GetContas
        {
            get
            {
                return Context == null ? null : Context.ContaFinanceiras.ToArray();
            }
        }

        public Lancamento LancamentoSaida
        {
            get { return _lancamentoSaida; }
            set
            {
                if (Equals(value, _lancamentoSaida)) return;
                _lancamentoSaida = value;
                OnPropertyChanged("LancamentoSaida");
            }
        }
        public Lancamento LancamentoPagamento
        {
            get { return _lancamentoPagamento; }
            set
            {
                if (Equals(value, _lancamentoPagamento)) return;
                _lancamentoPagamento = value;
                OnPropertyChanged("LancamentoPagamento");
            }
        }

        public decimal Valor
        {
            get { return _valor; }
            set
            {
                if (value == _valor) return;
                _valor = value;
                OnPropertyChanged("Valor");

                AtualizarSaida();
                AtualizarPagamento();
            }
        }

        public ContaFinanceira Conta
        {
            get { return _conta; }
            set
            {
                if (Equals(value, _conta)) return;
                _conta = value;
                OnPropertyChanged("Conta");
            }
        }

        private TipoDeMovimento TipoDeMovimentoSaida
        {
            get
            {
                return Entity.TipoDeMovimento == TipoDeMovimento.Despesa ? TipoDeMovimento.Despesa : TipoDeMovimento.Receita;
            }
        }
        private TipoDeMovimento TipoDeMovimentoEntrada
        {
            get
            {
                return Entity.TipoDeMovimento == TipoDeMovimento.Despesa ? TipoDeMovimento.Receita : TipoDeMovimento.Despesa;
            }
        }

        private void AtualizarSaida()
        {
            if (LancamentoSaida != null)
            {
                LancamentoSaida.Categoria = Context.GetCategoriaEmprestimo(); ;
                LancamentoSaida.DataDoLancamento = Entity.DataDoLancamento;
                if (Entity.Pessoa != null)
                    LancamentoSaida.Nome = "Empréstimo " +
                                           (Entity.TipoDeMovimento == TipoDeMovimento.Receita ? "contraído com " : "feito à ") +
                                           Entity.Pessoa.Nome;

                if (LancamentoSaida.Movimentos.Any())
                {
                    var movimento = LancamentoSaida.Movimentos.Single();
                    movimento.DataDoMovimento = Entity.DataDoLancamento;
                    movimento.ValorAbsoluto = Valor;
                    movimento.TipoDeMovimento = TipoDeMovimentoSaida;
                    movimento.Conta = Conta;
                    movimento.Historico = LancamentoSaida.Nome;
                }
            }
        }
        private void AtualizarPagamento()
        {
            if (LancamentoPagamento != null)
            {
                LancamentoPagamento.DataDoLancamento = DataDoPagamento;
                LancamentoPagamento.Categoria = Context.GetCategoriaEmprestimo();
                if (Entity.Pessoa != null)
                    LancamentoPagamento.Nome = (Entity.TipoDeMovimento == TipoDeMovimento.Receita ? "Pagamento de Empréstimo" : "Recebimento do Empréstimo ") + 
                                               (Entity.TipoDeMovimento == TipoDeMovimento.Receita ? "contraído com " : "feito à ") +
                                               Entity.Pessoa.Nome;

                if (LancamentoPagamento.Movimentos.Any())
                {
                    var movimento = LancamentoPagamento.Movimentos.Single();
                    movimento.DataDoMovimento = DataDoPagamento;
                    movimento.ValorAbsoluto = Valor;
                    movimento.TipoDeMovimento = TipoDeMovimentoEntrada;
                    movimento.Conta = Conta;
                    movimento.Historico = LancamentoPagamento.Nome;
                }
                
            }
        }

        public bool PagamentoRealizado
        {
            get { return _pagamentoRealizado; }
            set
            {
                if (value.Equals(_pagamentoRealizado)) return;
                _pagamentoRealizado = value;
                OnPropertyChanged("PagamentoRealizado");

                if (PagamentoRealizado)
                {
                    if (LancamentoPagamento == null)
                    {
                        LancamentoPagamento = new Lancamento
                        {
                            Usuario = Context.GetUsuarioLogado()
                        };
                        Context.Lancamentos.Add(LancamentoPagamento);
                        LancamentoPagamento.Movimentos.Add(new Movimento
                        {
                            Lancamento = LancamentoPagamento,
                            TipoDeMovimento = TipoDeMovimentoEntrada
                        });
                        AtualizarPagamento();
                        Entity.Pagamento = LancamentoPagamento;
                    }
                }
                else
                {
                    if (LancamentoPagamento != null && Context.Lancamentos.Local.Contains(LancamentoPagamento))
                    {
                        foreach (var movimento in LancamentoPagamento.Movimentos.ToArray())
                        {
                            Context.Movimentos.Remove(movimento);
                        }
                        Context.Lancamentos.Remove(LancamentoPagamento);
                    }
                        
                    LancamentoPagamento = null;
                }
            }
        }

        public DateTime DataDoPagamento
        {
            get { return _dataDoPagamento; }
            set
            {
                if (value.Equals(_dataDoPagamento)) return;
                _dataDoPagamento = value;
                OnPropertyChanged("DataDoPagamento");

                AtualizarPagamento();
            }
        }

        public Enum[] GetTipoMovimentos
        {
            get { return Enum.GetValues(typeof(TipoDeMovimento)).Cast<Enum>().ToArray(); }
        }

        protected override void AfterSetAction()
        {
            base.AfterSetAction();

            if (Action == CRUDOperationType.Create)
            {
                Entity.Usuario = Context.GetUsuarioLogado();
                Entity.TipoDeMovimento = TipoDeMovimentoSaida;
                Entity.DataDoLancamento = DateTime.Now.Date;
            }

            LancamentoSaida = Entity.Saida;
            LancamentoPagamento = Entity.Pagamento;

            if (LancamentoSaida == null)
            {
                LancamentoSaida = new Lancamento
                {
                    Usuario = Context.GetUsuarioLogado()
                };
                Entity.Saida = LancamentoSaida;
                Context.Lancamentos.Add(LancamentoSaida);
                LancamentoSaida.DataDoLancamento = DateTime.Now.Date;

                LancamentoSaida.Movimentos.Add(new Movimento
                {
                    Lancamento = LancamentoSaida,
                    TipoDeMovimento =  TipoDeMovimentoSaida
                });
            }

            PagamentoRealizado = Entity.Pagamento != null;
            DataDoPagamento = Entity.Pagamento != null ? Entity.Pagamento.DataDoLancamento : DateTime.Now.Date;
            Valor = LancamentoSaida.Valor;
            Conta = LancamentoSaida.Movimentos.Single().Conta;

            AtualizarPagamento();
            AtualizarSaida();
        }

        protected override void BeforeSave()
        {
            base.BeforeSave();
            AtualizarSaida();
            AtualizarPagamento();
        }
    }
}